package cn.tedu.fruitshop.service.impl;

import cn.tedu.fruitshop.config.SecurityConfiguration;
import cn.tedu.fruitshop.ex.ServiceException;
import cn.tedu.fruitshop.mapper.UserMapper;
import cn.tedu.fruitshop.pojo.dto.UserAddNewDTO;
import cn.tedu.fruitshop.pojo.dto.UserLoginDTO;
import cn.tedu.fruitshop.pojo.entity.User;
import cn.tedu.fruitshop.pojo.vo.UserListItemVO;
import cn.tedu.fruitshop.pojo.vo.UserListVO;
import cn.tedu.fruitshop.pojo.vo.UserStandardVO;
import cn.tedu.fruitshop.security.UserDetails;
import cn.tedu.fruitshop.service.UserService;
import cn.tedu.fruitshop.web.ServiceCode;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author www
 * @create 2022-11-03 15:06
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    //创建密钥
    @Value("${fruitshop.jwt.secret-key}")
    String secretKey;

    @Value("${fruitshop.jwt.duration}")
    long duration;

    @Autowired
    private SecurityConfiguration securityConfiguration;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    AuthenticationManager authenticationManager;

    @Override
    public String login(UserLoginDTO userLoginDTO) {
        log.debug("开始执行【登录】的业务，参数：{}", userLoginDTO);
//        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
//        String encode = passwordEncoder.encode(userLoginDTO.getPassword());
        //认证信息
        Authentication authentication =
                new UsernamePasswordAuthenticationToken(userLoginDTO.getUsername(), userLoginDTO.getPassword());
        log.debug("根据身份验证管理者。开始身份验证（认证信息）");
        Authentication authenticate =
                authenticationManager.authenticate(authentication);
        //根据security框架的文本上下文持有者。获取文本上下文。设置身份验证（身份验证）
        //SecurityContextHolder.getContext().setAuthentication(authenticate);
        log.debug("认证：{}", authenticate);
        //获取主要数据，即（身份验证的信息）
        Object principal = authenticate.getPrincipal();
        Collection<? extends GrantedAuthority> authorities = authenticate.getAuthorities();
        //将信息强转成Security框架中的user，
        UserDetails userDetails = (UserDetails) principal;
        Long id = userDetails.getId();
        String username = userDetails.getUsername();
        String authoritiesJSONString = JSON.toJSONString(authorities);
        //获取验证成功的User的用户名
        Date date = new Date(System.currentTimeMillis() + 1000L * 60 * duration);
        //创建map集合，以key-value 的形式存放用户信息。
        Map<String, Object> claims = new HashMap<>();
        //将用户信息存放到集合
        claims.put("id", id);
        claims.put("username", username);
        claims.put("authoritiesJSONString", authoritiesJSONString);
        //创建Jwt数据
        String jwt = Jwts.builder()
                //设置头部的算法+类型
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "jwt")
                //存放数据
                .setClaims(claims)
                //有效期
                .setExpiration(date)
                //签名认证
                .signWith(SignatureAlgorithm.HS256, secretKey)
                //构建一个紧凑的安全的字符串
                .compact();
        log.debug("JWT编码：{}", jwt);
        return jwt;
    }

    @Override
    public void reg(UserAddNewDTO userAddNewDTO) {
        log.debug("开始处理注册用户的业务,参数为:{}", userAddNewDTO);
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encode = passwordEncoder.encode(userAddNewDTO.getPassword());
        User user = new User();
        BeanUtils.copyProperties(userAddNewDTO, user);
        user.setPassword(encode);
        user.setEnable(1);
        int rows = userMapper.insert(user);
        log.debug("开始注册结果为:{}", rows);
        if (rows != 1) {
            String message = "操作失败,服务器繁忙，请稍后再试";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
    }

    @Override
    public UserStandardVO getStandardByUsername(String username) {
        log.debug("开始处理根据用户名查询个人信息的业务,参数为:{}", username);
        UserStandardVO resultByUsername = userMapper.getStandardByUsername(username);
        if (resultByUsername == null) {
            return resultByUsername;
        }
        log.debug("查询结果为:{}", resultByUsername);
        return resultByUsername;
    }


}
